<html lang="en-US">

<head>
    
<title>Go 大杀器之性能剖析 PProf - 花落雨忧</title>

<meta property="og:title" content="Go 大杀器之性能剖析 PProf - 花落雨忧">



    



    
    <meta property="description" content="写了几吨代码，实现了几百个接口。功能测试也通过了，终于成功的部署上线了
结果，性能不佳，什么鬼？😭
[&amp;hellip;] 想要进行性能优化，首先瞩目在 Go 自身提供的工具链来作为分析依据，本文将带你学习、使用 Go 后花园，涉及如下：
[&amp;hellip;] pprof 是用于可视化和分析性能分析数据的工具
pprof 以 profile.proto 读取分析样本的集合，并生成报告以可视化并帮助分 &amp;hellip;">
    <meta property="og:description" content="写了几吨代码，实现了几百个接口。功能测试也通过了，终于成功的部署上线了
结果，性能不佳，什么鬼？😭
[&amp;hellip;] 想要进行性能优化，首先瞩目在 Go 自身提供的工具链来作为分析依据，本文将带你学习、使用 Go 后花园，涉及如下：
[&amp;hellip;] pprof 是用于可视化和分析性能分析数据的工具
pprof 以 profile.proto 读取分析样本的集合，并生成报告以可视化并帮助分 &amp;hellip;">
    






<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1">

<link rel="shortcut icon" href="https://www.lican.site/logo/logo.png" type="image/x-icon" />



<link rel="stylesheet" href="/css/style.min.css" />

<link rel="stylesheet" href="/css/reset.min.css" />




<script src="https://www.lican.site/js/highlight.min.js"></script>

<script>
hljs.configure({ ignoreUnescapedHTML: true })
hljs.highlightAll();
</script>


<script src="https://www.lican.site/js/jquery.min.js"></script>




<link href="https://www.lican.site/css/hugo-code.min.css" rel="stylesheet" />



    <style>
        .post-content img {
            max-width: 400px;
        }
    </style>
</head>

<body id="period" class="home blog">
    <a class="skip-content" href="#main">Press "Enter" to skip to content</a>
    <div id="overflow-container" class="overflow-container">
        <header class="site-header" id="site-header" role="banner">
    <div class="max-width">
        <div id="title-container" class="title-container">
            <div id="site-title" class="site-title"><a href="/">花落雨忧</a></div>
            <p class="tagline">思所及 力所行 方为真.</p>
        </div>
        
        <div id="menu-primary-container" class="menu-primary-container">
            <div class="icon-container">
            </div>
            <div id="menu-primary" class="menu-container menu-primary" role="navigation">
                <nav class="menu">
                    <ul id="menu-primary-items" class="menu-primary-items">
                        
                        
                        <li id="menu-item-0"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/posts" aria-current="page" tabindex="0">首页</a></li>
                        
                        <li id="menu-item-1"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/tech/" aria-current="page" tabindex="1">技术文档</a></li>
                        
                        <li id="menu-item-2"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/article/" aria-current="page" tabindex="2">文章</a></li>
                        
                        <li id="menu-item-3"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/project/" aria-current="page" tabindex="3">项目</a></li>
                        
                        <li id="menu-item-4"
                            class="menu-item menu-item-type-custom menu-item-object-custom ">
                            <a href="/about/" aria-current="page" tabindex="4">关于</a></li>
                        
                    </ul>
                </nav>
            </div>
        </div>
    </div>
</header>
        <div id="primary-container" class="primary-container">
            <div class="max-width">
                <section id="main" class="main" role="main">
                    <div id="loop-container" class="loop-container">
                        <div
                            class="post type-post status-publish format-standard hentry entry">
                            <article>
                                <div class="post-container">
                                    <div class="post-header">
                                        <h2 class="post-title">
                                            <a href="/posts/go/tools/2018-09-15-go-tool-pprof/">Go 大杀器之性能剖析 PProf</a>
                                        </h2>
                                        
                                        <div class="post-byline">Published on
                                            <a class="date" href="javascript:;">2018/09/15</a>
                                            
                                            
                                            
                                            By 
                                            <a class="author" href="javascript:;">煎鱼</a></div>
                                            
                                        
                                    </div>
                                    <div class="post-content">
                                        <h2 id="前言">前言</h2>
<p>写了几吨代码，实现了几百个接口。功能测试也通过了，终于成功的部署上线了</p>
<p>结果，性能不佳，什么鬼？😭</p>
<h2 id="想做性能分析">想做性能分析</h2>
<h3 id="pprof">PProf</h3>
<p>想要进行性能优化，首先瞩目在 Go 自身提供的工具链来作为分析依据，本文将带你学习、使用 Go 后花园，涉及如下：</p>
<ul>
<li>runtime/pprof：采集程序（非 Server）的运行数据进行分析</li>
<li>net/http/pprof：采集 HTTP Server 的运行时数据进行分析</li>
</ul>
<h3 id="是什么">是什么</h3>
<p>pprof 是用于可视化和分析性能分析数据的工具</p>
<p>pprof 以 <a href="https://github.com/google/pprof/blob/master/proto/profile.proto">profile.proto</a> 读取分析样本的集合，并生成报告以可视化并帮助分析数据（支持文本和图形报告）</p>
<p>profile.proto 是一个 Protocol Buffer v3 的描述文件，它描述了一组 callstack 和 symbolization 信息， 作用是表示统计分析的一组采样的调用栈，是很常见的 stacktrace 配置文件格式</p>
<h3 id="支持什么使用模式">支持什么使用模式</h3>
<ul>
<li>Report generation：报告生成</li>
<li>Interactive terminal use：交互式终端使用</li>
<li>Web interface：Web 界面</li>
</ul>
<h3 id="可以做什么">可以做什么</h3>
<ul>
<li>CPU Profiling：CPU 分析，按照一定的频率采集所监听的应用程序 CPU（含寄存器）的使用情况，可确定应用程序在主动消耗 CPU 周期时花费时间的位置</li>
<li>Memory Profiling：内存分析，在应用程序进行堆分配时记录堆栈跟踪，用于监视当前和历史内存使用情况，以及检查内存泄漏</li>
<li>Block Profiling：阻塞分析，记录 goroutine 阻塞等待同步（包括定时器通道）的位置</li>
<li>Mutex Profiling：互斥锁分析，报告互斥锁的竞争情况</li>
</ul>
<h2 id="一个简单的例子">一个简单的例子</h2>
<p>我们将编写一个简单且有点问题的例子，用于基本的程序初步分析</p>
<h3 id="编写-demo-文件">编写 demo 文件</h3>
<p>（1）demo.go，文件内容：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>

<span style="color:#f92672">import</span> (
	<span style="color:#e6db74">&#34;log&#34;</span>
	<span style="color:#e6db74">&#34;net/http&#34;</span>
	<span style="color:#a6e22e">_</span> <span style="color:#e6db74">&#34;net/http/pprof&#34;</span>
	<span style="color:#e6db74">&#34;github.com/EDDYCJY/go-pprof-example/data&#34;</span>
)

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
	<span style="color:#66d9ef">go</span> <span style="color:#66d9ef">func</span>() {
		<span style="color:#66d9ef">for</span> {
			<span style="color:#a6e22e">log</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#a6e22e">data</span>.<span style="color:#a6e22e">Add</span>(<span style="color:#e6db74">&#34;https://github.com/EDDYCJY&#34;</span>))
		}
	}()

	<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">ListenAndServe</span>(<span style="color:#e6db74">&#34;0.0.0.0:6060&#34;</span>, <span style="color:#66d9ef">nil</span>)
}
</code></pre></div><p>（2）data/d.go，文件内容：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#f92672">package</span> <span style="color:#a6e22e">data</span>

<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">datas</span> []<span style="color:#66d9ef">string</span>

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">Add</span>(<span style="color:#a6e22e">str</span> <span style="color:#66d9ef">string</span>) <span style="color:#66d9ef">string</span> {
	<span style="color:#a6e22e">data</span> <span style="color:#f92672">:=</span> []byte(<span style="color:#a6e22e">str</span>)
	<span style="color:#a6e22e">sData</span> <span style="color:#f92672">:=</span> string(<span style="color:#a6e22e">data</span>)
	<span style="color:#a6e22e">datas</span> = append(<span style="color:#a6e22e">datas</span>, <span style="color:#a6e22e">sData</span>)

	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">sData</span>
}

</code></pre></div><p>运行这个文件，你的 HTTP 服务会多出 /debug/pprof 的 endpoint 可用于观察应用程序的情况</p>
<h3 id="分析">分析</h3>
<h4 id="一通过-web-界面">一、通过 Web 界面</h4>
<p>查看当前总览：访问 <code>http://127.0.0.1:6060/debug/pprof/</code></p>
<pre><code>/debug/pprof/

profiles:
0	block
5	goroutine
3	heap
0	mutex
9	threadcreate

full goroutine stack dump
</code></pre><p>这个页面中有许多子页面，咱们继续深究下去，看看可以得到什么？</p>
<ul>
<li>cpu（CPU Profiling）: <code>$HOST/debug/pprof/profile</code>，默认进行 30s 的 CPU Profiling，得到一个分析用的 profile 文件</li>
<li>block（Block Profiling）：<code>$HOST/debug/pprof/block</code>，查看导致阻塞同步的堆栈跟踪</li>
<li>goroutine：<code>$HOST/debug/pprof/goroutine</code>，查看当前所有运行的 goroutines 堆栈跟踪</li>
<li>heap（Memory Profiling）: <code>$HOST/debug/pprof/heap</code>，查看活动对象的内存分配情况</li>
<li>mutex（Mutex Profiling）：<code>$HOST/debug/pprof/mutex</code>，查看导致互斥锁的竞争持有者的堆栈跟踪</li>
<li>threadcreate：<code>$HOST/debug/pprof/threadcreate</code>，查看创建新 OS 线程的堆栈跟踪</li>
</ul>
<h4 id="二通过交互式终端使用">二、通过交互式终端使用</h4>
<p>（1）go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ go tool pprof http://localhost:6060/debug/pprof/profile<span style="color:#ae81ff">\?</span>seconds<span style="color:#ae81ff">\=</span><span style="color:#ae81ff">60</span>

Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds<span style="color:#f92672">=</span><span style="color:#ae81ff">60</span>
Saved profile in /Users/eddycjy/pprof/pprof.samples.cpu.007.pb.gz
Type: cpu
Duration: 1mins, Total samples <span style="color:#f92672">=</span> 26.55s <span style="color:#f92672">(</span>44.15%<span style="color:#f92672">)</span>
Entering interactive mode <span style="color:#f92672">(</span>type <span style="color:#e6db74">&#34;help&#34;</span> <span style="color:#66d9ef">for</span> commands, <span style="color:#e6db74">&#34;o&#34;</span> <span style="color:#66d9ef">for</span> options<span style="color:#f92672">)</span>
<span style="color:#f92672">(</span>pprof<span style="color:#f92672">)</span>
</code></pre></div><p>执行该命令后，需等待 60 秒（可调整 seconds 的值），pprof 会进行 CPU Profiling。结束后将默认进入 pprof 的交互式命令模式，可以对分析的结果进行查看或导出。具体可执行 <code>pprof help</code> 查看命令说明</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">(</span>pprof<span style="color:#f92672">)</span> top10
Showing nodes accounting <span style="color:#66d9ef">for</span> 25.92s, 97.63% of 26.55s total
Dropped <span style="color:#ae81ff">85</span> nodes <span style="color:#f92672">(</span>cum &lt;<span style="color:#f92672">=</span> 0.13s<span style="color:#f92672">)</span>
Showing top <span style="color:#ae81ff">10</span> nodes out of <span style="color:#ae81ff">21</span>
      flat  flat%   sum%        cum   cum%
    23.28s 87.68% 87.68%     23.29s 87.72%  syscall.Syscall
     0.77s  2.90% 90.58%      0.77s  2.90%  runtime.memmove
     0.58s  2.18% 92.77%      0.58s  2.18%  runtime.freedefer
     0.53s  2.00% 94.76%      1.42s  5.35%  runtime.scanobject
     0.36s  1.36% 96.12%      0.39s  1.47%  runtime.heapBitsForObject
     0.35s  1.32% 97.44%      0.45s  1.69%  runtime.greyobject
     0.02s 0.075% 97.51%     24.96s 94.01%  main.main.func1
     0.01s 0.038% 97.55%     23.91s 90.06%  os.<span style="color:#f92672">(</span>*File<span style="color:#f92672">)</span>.Write
     0.01s 0.038% 97.59%      0.19s  0.72%  runtime.mallocgc
     0.01s 0.038% 97.63%     23.30s 87.76%  syscall.Write
</code></pre></div><ul>
<li>flat：给定函数上运行耗时</li>
<li>flat%：同上的 CPU 运行耗时总比例</li>
<li>sum%：给定函数累积使用 CPU 总比例</li>
<li>cum：当前函数加上它之上的调用运行总耗时</li>
<li>cum%：同上的 CPU 运行耗时总比例</li>
</ul>
<p>最后一列为函数名称，在大多数的情况下，我们可以通过这五列得出一个应用程序的运行情况，加以优化 🤔</p>
<p>（2）go tool pprof http://localhost:6060/debug/pprof/heap</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ go tool pprof http://localhost:6060/debug/pprof/heap
Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap
Saved profile in /Users/eddycjy/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.008.pb.gz
Type: inuse_space
Entering interactive mode <span style="color:#f92672">(</span>type <span style="color:#e6db74">&#34;help&#34;</span> <span style="color:#66d9ef">for</span> commands, <span style="color:#e6db74">&#34;o&#34;</span> <span style="color:#66d9ef">for</span> options<span style="color:#f92672">)</span>
<span style="color:#f92672">(</span>pprof<span style="color:#f92672">)</span> top
Showing nodes accounting <span style="color:#66d9ef">for</span> 837.48MB, 100% of 837.48MB total
      flat  flat%   sum%        cum   cum%
  837.48MB   100%   100%   837.48MB   100%  main.main.func1
</code></pre></div><ul>
<li>
<p>-inuse_space：分析应用程序的常驻内存占用情况</p>
</li>
<li>
<p>-alloc_objects：分析应用程序的内存临时分配情况</p>
</li>
</ul>
<p>（3） go tool pprof http://localhost:6060/debug/pprof/block</p>
<p>（4） go tool pprof http://localhost:6060/debug/pprof/mutex</p>
<h4 id="三pprof-可视化界面">三、PProf 可视化界面</h4>
<p>这是令人期待的一小节。在这之前，我们需要简单的编写好测试用例来跑一下</p>
<h5 id="编写测试用例">编写测试用例</h5>
<p>（1）新建 data/d_test.go，文件内容：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#f92672">package</span> <span style="color:#a6e22e">data</span>

<span style="color:#f92672">import</span> <span style="color:#e6db74">&#34;testing&#34;</span>

<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">url</span> = <span style="color:#e6db74">&#34;https://github.com/EDDYCJY&#34;</span>

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">TestAdd</span>(<span style="color:#a6e22e">t</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">testing</span>.<span style="color:#a6e22e">T</span>) {
	<span style="color:#a6e22e">s</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">Add</span>(<span style="color:#a6e22e">url</span>)
	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">s</span> <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;&#34;</span> {
		<span style="color:#a6e22e">t</span>.<span style="color:#a6e22e">Errorf</span>(<span style="color:#e6db74">&#34;Test.Add error!&#34;</span>)
	}
}

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">BenchmarkAdd</span>(<span style="color:#a6e22e">b</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">testing</span>.<span style="color:#a6e22e">B</span>) {
	<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> &lt; <span style="color:#a6e22e">b</span>.<span style="color:#a6e22e">N</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span> {
		<span style="color:#a6e22e">Add</span>(<span style="color:#a6e22e">url</span>)
	}
}
</code></pre></div><p>（2）执行测试用例</p>
<pre><code>$ go test -bench=. -cpuprofile=cpu.prof
pkg: github.com/EDDYCJY/go-pprof-example/data
BenchmarkAdd-4   	10000000	       187 ns/op
PASS
ok  	github.com/EDDYCJY/go-pprof-example/data	2.300s
</code></pre><p>-memprofile 也可以了解一下</p>
<h5 id="启动-pprof-可视化界面">启动 PProf 可视化界面</h5>
<h6 id="方法一">方法一：</h6>
<pre><code>$ go tool pprof -http=:8080 cpu.prof
</code></pre><h6 id="方法二">方法二：</h6>
<pre><code>$ go tool pprof cpu.prof
$ (pprof) web
</code></pre><p>如果出现 <code>Could not execute dot; may need to install graphviz.</code>，就是提示你要安装 <code>graphviz</code> 了 （请右拐谷歌）</p>
<h5 id="查看-pprof-可视化界面">查看 PProf 可视化界面</h5>
<p>（1）Top</p>
<p><img src="https://s2.ax1x.com/2020/02/15/1xlsYD.jpg" alt="image"></p>
<p>（2）Graph</p>
<p><img src="https://s2.ax1x.com/2020/02/15/1xlgld.jpg" alt="image"></p>
<p>框越大，线越粗代表它占用的时间越大哦</p>
<p>（3）Peek</p>
<p><img src="https://s2.ax1x.com/2020/02/15/1xlROI.jpg" alt="image"></p>
<p>（4）Source</p>
<p><img src="https://s2.ax1x.com/2020/02/15/1xl4Tf.jpg" alt="image"></p>
<p>通过 PProf 的可视化界面，我们能够更方便、更直观的看到 Go 应用程序的调用链、使用情况等，并且在 View 菜单栏中，还支持如上多种方式的切换</p>
<p>你想想，在烦恼不知道什么问题的时候，能用这些辅助工具来检测问题，是不是瞬间效率翻倍了呢 👌</p>
<h4 id="四pprof-火焰图">四、PProf 火焰图</h4>
<p>另一种可视化数据的方法是火焰图，需手动安装原生 PProf 工具：</p>
<p>（1） 安装 PProf</p>
<pre><code>$ go get -u github.com/google/pprof
</code></pre><p>（2） 启动 PProf 可视化界面:</p>
<pre><code>$ pprof -http=:8080 cpu.prof
</code></pre><p>（3） 查看 PProf 可视化界面</p>
<p>打开 PProf 的可视化界面时，你会明显发现比官方工具链的 PProf 精致一些，并且多了 Flame Graph（火焰图）</p>
<p>它就是本次的目标之一，它的最大优点是动态的。调用顺序由上到下（A -&gt; B -&gt; C -&gt; D），每一块代表一个函数，越大代表占用 CPU 的时间更长。同时它也支持点击块深入进行分析！</p>
<p><img src="https://s2.ax1x.com/2020/02/15/1xlj00.jpg" alt="image"></p>
<h2 id="总结">总结</h2>
<p>在本章节，粗略地介绍了 Go 的性能利器 PProf。在特定的场景中，PProf 给定位、剖析问题带了极大的帮助</p>
<p>希望本文对你有所帮助，另外建议能够自己实际操作一遍，最好是可以深入琢磨一下，内含大量的用法、知识点 🤓</p>
<h2 id="思考题">思考题</h2>
<p>你很优秀的看到了最后，那么有两道简单的思考题，希望拓展你的思路</p>
<p>（1）flat 一定大于 cum 吗，为什么？什么场景下 cum 会比 flat 大？</p>
<p>（2）本章节的 demo 代码，有什么性能问题？怎么解决它？</p>


                                        
                                        
                                        
                                        <div class="rp4wp-related-posts">
                                            <h3>相关文章</h3>
                                            <ul>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.site/posts/go/gin/2018-09-01-nginx/">「连载十七」用Nginx部署Go应用</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.site/posts/go/gin/2018-08-26-makefile/">「番外」请入门 Makefile</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.site/posts/go/gin/2018-07-07-font/">「连载十六」在图片上绘制文字</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.site/posts/go/gin/2018-07-05-image/">「连载十五」生成二维码、合并海报</a>
                                                    </div>
                                                </li>
                                                
                                                <li>
                                                    <div class="rp4wp-related-post-content">
                                                        <a
                                                            href="https://www.lican.site/posts/go/gin/2018-06-14-excel/">「连载十四」实现导出、导入 Excel</a>
                                                    </div>
                                                </li>
                                                
                                            </ul>
                                        </div>
                                        
                                        
                                    </div>

                                    
                                    
                                    

                                    
                                    <div class="post-meta">
                                        
                                        
                                        <div class="post-tags">
                                            <ul>
                                            
                                            <li>
                                                <a href="/tags/go" title="View all posts tagged match">go</a>
                                            </li>
                                            
                                            </ul>
                                        </div>
                                        
                                        
                                        <nav class="further-reading">
                                            
                                            <div class="previous">
                                                <span>&lt;&lt; Prev</span>
                                                <a href="https://www.lican.site/posts/go/gin/2018-09-01-nginx/"
                                                    rel="prev">「连载十七」用Nginx部署Go应用</a> </div>
                                            
                                            
                                            <div class="next">
                                                <span>Next >></span>
                                                <a href="https://www.lican.site/posts/go/grpc/2018-09-22-install/">「连载一」gRPC及相关介绍</a> 
                                            </div>
                                            
                                        </nav>
                                    </div>
                                    
                                    

                                    
                                    
                                    

                                </div>
                            </article>
                        </div>
                    </div>
                </section>
                <aside class="sidebar sidebar-primary" id="sidebar-primary" role="complementary">
    <h1 class="screen-reader-text">Sidebar</h1>
    

    
    
    <section id="text-2" class="widget widget_text">
        <div class="textwidget">
            
            <div id="profile">
                <div id="profile_picture"><img src="https://www.lican.site/logo/logo.png"></div>
                <div id="profile_intro">
                    <p><span class="name">Lican</span></p>
                    <p class="intro">全栈开发者，爱好造轮子。</p>
                </div>
            </div>
            
            <p>
                <script type="text/javascript">
                    (function ($) {
                        $(document).ready(function () {
                            var menuPrimaryContainer = $('#menu-primary-container');
                            var profile = $('#text-2');
                            $('#toggle-navigation').click(function () {
                                if (menuPrimaryContainer.hasClass('open')) {
                                    profile.removeClass('open');
                                } else {
                                    profile.addClass('open');
                                }
                            });
                        });
                    })(jQuery);
                </script>
            </p>
        </div>
    </section>
    
    
    
    
    
    <section id="text-5" class="widget widget_text">
        <h2 class="widget-title">开源项目</h2>
        <div class="textwidget">
            <div id="projects" style="line-height: 22px;">
                
                <a href="https://github.com/idoubi/gonews"
                    target="_blank">gonews</a>: &nbsp;Daily news for golang<br>
                
                <a href="https://github.com/idoubi/sql2struct"
                    target="_blank">sql2struct</a>: &nbsp;Generate go struct according to SQL<br>
                
                <a href="https://github.com/idoubi/goz"
                    target="_blank">goz</a>: &nbsp;Request library used in golang<br>
                
        </div>
    </section>
    
    

    
    
    
    
    

    
    
    

    
    
    

    
    
    
    
</aside>
            </div>
        </div>

        <footer id="site-footer" class="site-footer" role="contentinfo">
    <div class="max-width">
    </div>
    <div class="footer">
        <div id="footercontent">
            © lican.vip All rights reserved<br/>
            Built with Hugo Theme <a href="https://github.com/idoubi/hugo-theme-period" target="_blank">Period</a>
        </div>
    </div>
</footer>

<script>
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?e8351b6d4626d5881d439ea1f6184baa";
      var s = document.getElementsByTagName("script")[0]; 
      s.parentNode.insertBefore(hm, s);
    })();
</script>
    
    
    </div>
    
</body>

</html>